import 'package:args/args.dart';
import 'package:simulator/core/mcu.dart';
import 'package:simulator/utils/constant.dart';
import 'package:simulator/utils/utils.dart';

class Options {
  static final Options _instance = Options._internal();

  Options._internal();

  static Options getInstance() => _instance;

  static late final CMD cmds;

  static final ArgParser argParser = ArgParser()
    ..addFlag('help',
        abbr: 'h', help: 'display this help and exit', negatable: false)
    ..addFlag('version',
        abbr: 'v',
        help: 'display version information and exit',
        negatable: false)
    ..addOption('arch',
        abbr: 'a',
        help: 'choose arch',
        defaultsTo: 'mcs51',
        allowed: ['mcs51', 'arm', 'risv', 'x86'])
    ..addOption('module', abbr: 'm', help: 'add some module to simulator')
    ..addOption('rom',
        defaultsTo: '67108864', help: 'rom size,dafult to 64M byte')
    ..addOption('ram', defaultsTo: '32768', help: 'ram size,dafult to 32K byte')
    ..addFlag('hex',
        abbr: 'x',
        defaultsTo: false,
        help: 'hex or bin format firmware',
        negatable: false)
    ..addOption('path', help: 'firmware path');

  void version() {
    print("SIMU emulator version: $simuVersion");
    print(simuCopyright);
  }

  void parserAndValidate(List<String> args) {
    try {
      ArgResults optDict = argParser.parse(args);
      cmds = CMD.fromJson(optDict);
      cmds.validate();
    } catch (e) {
      Utils.getInstance().abort(e.toString());
    }
  }

  void help() {
    version();
    print(argParser.usage);
    print("During emulation, the following keys are useful:\n"
        "ctrl-alt-f      toggle full screen\n"
        "ctrl-alt-n      switch to virtual console 'n'\n"
        "ctrl-alt-g      toggle mouse and keyboard grab\n"
        "\n"
        "When using -nographic, press 'ctrl-a h' to get some help.\n"
        "\n");
  }
}

///命令行大于配置文件
class CMD {
  final MCUType arch;
  final String? module;
  final bool isHex;
  final String path;
  final int romSize;
  final int ramSize;
  const CMD(
      {this.isHex = true,
      this.path = '',
      this.romSize = 0,
      this.ramSize = 0,
      this.arch = MCUType.unkown,
      this.module});
  factory CMD.fromJson(ArgResults json) {
    if (!json.wasParsed('arch')) {
      throw 'must choose one arch';
    }
    if (!json.wasParsed('path')) {
      throw 'must set firmware  path';
    }
    return CMD(
        arch: MCUTypeOp.getType(json['arch']),
        module: json['arch'],
        path: json['path'],
        isHex: json['hex'],
        romSize: int.parse(json['rom']),
        ramSize: int.parse(json['ram']));
  }

  void validate() {}

  CMD copyWith({int? romSize, int? ramSize, MCUType? arch}) => CMD(
      arch: arch ?? this.arch,
      module: module,
      romSize: romSize ?? this.romSize,
      ramSize: ramSize ?? this.ramSize,
      path: path,
      isHex: isHex);
}
